home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 05 - 1989 / 05.04 Apr 89 / Scroller Code / ScrollerMain.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-08-26  |  16.8 KB  |  782 lines  |  [TEXT/KAHL]

  1. /*    Application Scroller, version 1.0 (August, 26, 1988)
  2.     
  3.     This application demonstrate features and use of the
  4.        Scrolling manager
  5.        
  6.     © 1988 John A. Nairn, All Rights Reserved    */
  7.  
  8. /*    Includes from Lightspeed C */
  9. #include <QuickDraw.h>
  10. #include <MacTypes.h>
  11. #include <FontMgr.h>
  12. #include <WindowMgr.h>
  13. #include <MenuMgr.h>
  14. #include <TextEdit.h>
  15. #include <EventMgr.h>
  16. #include <DeskMgr.h>
  17. #include <DialogMgr.h>
  18. #include <ToolboxUtil.h>
  19. #include <ControlMgr.h>
  20. #include "ScrollMgr.h"        /*Scrolling Manager header*/
  21.  
  22. enum { apple_menu=255,file_menu,edit_menu };
  23. enum { drawCursor=300,handCursor,joyCursor };
  24. #define sample_text 500
  25. #define about_dlog 998
  26. #define NIL 0L                    /* Some constants */
  27. #define RULERWIDTH 15
  28. #define TOOLWIDTH 20
  29. #define about_item 1            /* Menu items */
  30. enum { new_window=1,graphic_window=3,text_edit_window,
  31.     vert_bar=6,horiz_bar,vert_ruler=9,horiz_ruler,
  32.     vert_tool_bar,horiz_tool_bar,quit=14 };
  33.  
  34. WindowPtr myWindow=NIL;            /* Global Variables */
  35. TEHandle myhTE=NIL;
  36. ScrollInfo scrollRecord;
  37. ScrollPtr myScrlp;
  38. Point polygon[200];
  39. Rect dragrect;
  40. int window_type=graphic_window,has_vBar=TRUE;
  41. int has_vRuler=FALSE,has_vTools=FALSE,has_hRuler=FALSE;
  42. int has_hTools=FALSE,has_hBar=TRUE;
  43. int vRuler,vTools,hRuler,hTools,polySize=0;
  44.  
  45. /* Main Program    - Initialize and start event loop */
  46.  
  47. main()
  48. {
  49.     MenuHandle menu;
  50.     Rect r;
  51.     
  52.     InitGraf(&thePort);
  53.     InitFonts();
  54.     InitWindows();
  55.     InitCursor();
  56.     FlushEvents(everyEvent,0);
  57.     InitMenus();
  58.     TEInit();
  59.     InitDialogs(0L);
  60.     r=screenBits.bounds;        /* Window dragging Rect */
  61.     SetRect(&dragrect,4,24,r.right-4,r.bottom-4);
  62.     menu=GetMenu(apple_menu);               /*DA menu*/
  63.     AddResMenu(menu,'DRVR');
  64.     InsertMenu(menu,0);
  65.     menu=GetMenu(file_menu);                /*File menu*/
  66.     InsertMenu(menu,0);
  67.     CheckItem(menu,window_type,TRUE);
  68.     CheckItem(menu,horiz_bar,has_vBar);
  69.     CheckItem(menu,vert_bar,has_hBar);
  70.     InsertMenu(GetMenu(edit_menu),0);        /*Edit Menu*/
  71.     MaintainMenus();
  72.     do_about();
  73.     event_loop();
  74. }
  75.  
  76. /*    Enable or Disable Edit Menu */
  77.  
  78. MaintainMenus()
  79. {
  80.     if(FrontWindow()==myWindow)
  81.     {    if(myhTE==NIL)
  82.             DisableItem(GetMHandle(edit_menu),0);
  83.         else
  84.             EnableItem(GetMHandle(edit_menu),0);
  85.     }
  86.     else
  87.         EnableItem(GetMHandle(edit_menu),0);
  88.     DrawMenuBar();
  89. }
  90.  
  91. /* Maintain cursor according to window type, keys
  92.     down, and mouse location    */
  93.  
  94. MaintainCursor()
  95. {
  96.     KeyMap theKeys;
  97.     RgnHandle drawRgn;
  98.     Point where;
  99.  
  100.     if(FrontWindow()!=myWindow)
  101.         return;    
  102.     else if(myWindow==NIL)
  103.         InitCursor();
  104.     else
  105.     {    drawRgn=ScrollSectRgn(myScrlp,myWindow);
  106.         GetMouse(&where);
  107.         if(!PtInRgn(where,drawRgn))
  108.             InitCursor();
  109.         else
  110.         {    GetKeys(&theKeys);
  111.             if((theKeys.Key[1]&4)&&(theKeys.Key[1]&1))
  112.                 SetCursor(*GetCursor(joyCursor));
  113.             else if(theKeys.Key[1]&4)
  114.                 SetCursor(*GetCursor(handCursor));
  115.             else if(myhTE!=NIL)
  116.                 SetCursor(*GetCursor(iBeamCursor));
  117.             else
  118.                 SetCursor(*GetCursor(drawCursor));
  119.         }
  120.         DisposeRgn(drawRgn);
  121.     }
  122. }
  123.  
  124. /*    Program main event loop    */
  125.  
  126. event_loop()
  127. {
  128.     EventRecord event;
  129.     Boolean valid;
  130.     char theChar;
  131.     
  132.     while (1)
  133.     {    SystemTask();
  134.         MaintainCursor();
  135.         if(myhTE!=NIL) TEIdle(myhTE);
  136.         valid=GetNextEvent(everyEvent,&event);
  137.         if (!valid) continue;
  138.         switch(event.what)
  139.         {    case mouseDown:
  140.                 do_mouse_down(&event);
  141.                 break;
  142.             case keyDown:
  143.             case autoKey:
  144.                 theChar=event.message&charCodeMask;
  145.                 if(event.modifiers&cmdKey)
  146.                 {    if(event.what!=autoKey)
  147.                         do_menu(MenuKey(theChar));
  148.                 }
  149.                 else
  150.                 {    if(myhTE!=NIL)
  151.                     {    if((**myhTE).teLength<32760)
  152.                         {    TEKey(theChar,myhTE);
  153.                             if(myScrlp->vScrollHdl!=NIL)
  154.                                 SetScroll(myScrlp,
  155.                                 (**myhTE).nLines,VertBar);
  156.                             FixTEInsertPt();
  157.                         }
  158.                         else
  159.                             SysBeep(10);    /* TE full */
  160.                     }
  161.                     else
  162.                         SysBeep(10);    /* bad key down    */
  163.                 }
  164.                 break;
  165.             case updateEvt:
  166.                 do_update(&event);
  167.                 break;
  168.             case activateEvt:
  169.                 do_activate((WindowPtr)event.message,
  170.                     event.modifiers&activeFlag);
  171.                 break;
  172.             default:
  173.                 break;
  174.         }
  175.     }
  176. }
  177.  
  178. /* Handle mouse down events */
  179.  
  180. do_mouse_down(eventp)
  181.     EventRecord *eventp;
  182. {
  183.     WindowPtr windowp;
  184.     int place_type=FindWindow(eventp->where,&windowp);
  185.     Boolean theshift;
  186.     KeyMap theKeys;
  187.     
  188.     switch(place_type)
  189.     {    case inMenuBar:
  190.             do_menu(MenuSelect(eventp->where));
  191.             break;
  192.         case inSysWindow:
  193.             SystemClick(eventp,windowp);
  194.             MaintainMenus();
  195.             break;
  196.         case inContent:
  197.             if(windowp!=FrontWindow())
  198.             {    SelectWindow(windowp);
  199.                 MaintainMenus();
  200.             }
  201.             else if(windowp==myWindow)
  202.             {    if(DoScroll(windowp,eventp->where)==FALSE)
  203.                 {    GetKeys(&theKeys);
  204.                     if((theKeys.Key[1]&4)&&
  205.                                 (theKeys.Key[1]&1))
  206.                         JoyStickScroll(eventp->where);
  207.                     else if(theKeys.Key[1]&4)
  208.                         DragScroll(eventp->where);
  209.                     else if(myhTE==NIL)
  210.                         TrackPoly(eventp->where);
  211.                     else
  212.                     {    GlobalToLocal(&eventp->where);
  213.                         if(PtInRect(eventp->where,
  214.                                     &(**myhTE).viewRect))
  215.                         {    if(eventp->modifiers&shiftKey)
  216.                                 theshift=TRUE;
  217.                             else
  218.                                 theshift=FALSE;
  219.                             ScrollTEClick(eventp->where,
  220.                                         theshift,myhTE);
  221.                         }
  222.                         else
  223.                             SysBeep(10);
  224.                     }
  225.                 }
  226.             }
  227.             break;
  228.         case inDrag:
  229.             DragWindow(windowp,eventp->where,&dragrect);
  230.             break;
  231.         case inGrow:
  232.             grow_window(windowp,eventp->where);
  233.             break;
  234.         case inGoAway:
  235.             if(TrackGoAway(windowp,eventp->where))
  236.             {    do_close(windowp);
  237.                 MaintainMenus();
  238.             }
  239.             break;
  240.         default:
  241.             break;
  242.     }
  243. }
  244.  
  245. /* Track mouse and draw a polygon - for Graphic windows*/
  246.  
  247. TrackPoly(where)
  248.     Point where;
  249. {
  250.     int lm,tm;
  251.     Point lastWhere;
  252.     Rect drawRect;
  253.     RgnHandle drawRgn;
  254.  
  255.     GlobalToLocal(&where);
  256.     ScrollSectRect(myScrlp,myWindow,&drawRect);
  257.     if(!PtInRect(where,&drawRect))
  258.     {    SysBeep(10);        /* illegal click location */
  259.         return;
  260.     }
  261.     GetMargins(myScrlp,&lm,inPixels,&tm,inPixels);
  262.     if(polySize==0)
  263.     {    polygon[polySize].h=where.h+lm;
  264.         polygon[polySize].v=where.v+tm;
  265.     }
  266.     else if(polySize==200)
  267.     {    SysBeep(10);
  268.         return;
  269.     }
  270.     drawRgn=ScrollSectRgn(myScrlp,myWindow);    
  271.     SetClip(drawRgn);    
  272.     PenMode(patXor);
  273.     MoveTo(polygon[polySize].h-lm,polygon[polySize].v-tm);
  274.     LineTo(where.h,where.v);
  275.     lastWhere=where;
  276.     while(StillDown())
  277.     {    GetMouse(&where);
  278.         if(PtInRgn(where,drawRgn))
  279.         {    if((where.h!=lastWhere.h)||
  280.                         (where.v!=lastWhere.v))
  281.             {    MoveTo(polygon[polySize].h-lm,
  282.                                 polygon[polySize].v-tm);
  283.                 LineTo(lastWhere.h,lastWhere.v);
  284.                 MoveTo(polygon[polySize].h-lm,
  285.                                 polygon[polySize].v-tm);
  286.                 LineTo(where.h,where.v);
  287.                 lastWhere=where;
  288.             }
  289.         }
  290.         else
  291.         {    MoveTo(polygon[polySize].h-lm,
  292.                         polygon[polySize].v-tm);
  293.             LineTo(lastWhere.h,lastWhere.v);
  294.             FollowMouse();
  295.             GetMargins(myScrlp,&lm,inPixels,&tm,inPixels);
  296.             MoveTo(polygon[polySize].h-lm,
  297.                             polygon[polySize].v-tm);
  298.             LineTo(where.h,where.v);
  299.             lastWhere=where;
  300.         }
  301.     }
  302.     MoveTo(polygon[polySize].h-lm,polygon[polySize].v-tm);
  303.     LineTo(lastWhere.h,lastWhere.v);
  304.     PenMode(patCopy);
  305.     if(lastWhere.h>drawRect.right)
  306.         lastWhere.h=drawRect.right;
  307.     if(lastWhere.h<drawRect.left)
  308.         lastWhere.h=drawRect.left;
  309.     if(lastWhere.v>drawRect.bottom)
  310.         lastWhere.v=drawRect.bottom;
  311.     if(lastWhere.v<drawRect.top)
  312.         lastWhere.v=drawRect.top;
  313.     MoveTo(polygon[polySize].h-lm,polygon[polySize].v-tm);
  314.     LineTo(lastWhere.h,lastWhere.v);
  315.     polygon[++polySize].h=lastWhere.h+lm;
  316.     polygon[polySize].v=lastWhere.v+tm;
  317.     ClipRect(&myWindow->portRect);
  318.     DisposeRgn(drawRgn);
  319. }
  320.  
  321. /* Close the scrolling demonstration window */
  322.  
  323. do_close(windowp)
  324.     WindowPtr windowp;
  325. {
  326.     if (myWindow!=NIL)
  327.     {    if(myhTE!=NIL)
  328.         {    ZeroScrap();
  329.             TEToScrap();
  330.             TEDispose(myhTE);
  331.         }
  332.         CloseWindow(windowp);
  333.         myWindow=NIL;
  334.         myhTE=NIL;
  335.     }
  336. }
  337.  
  338. /* Handle menu command events */
  339.  
  340. do_menu(command)
  341.     long command;
  342. {
  343.     int menu_id=HiWord(command);
  344.     int item=LoWord(command);
  345.     if(menu_id!=0)
  346.         do_menu_item(menu_id,item);
  347. }
  348.  
  349. /* Do a menu command */
  350.  
  351. do_menu_item(menu_id,item)
  352.     int menu_id,item;
  353. {
  354.     char item_name[32];
  355.     int newCheck;
  356.     
  357.     switch(menu_id)
  358.     {    case apple_menu:
  359.             switch(item)
  360.             {    case about_item:
  361.                     do_about();
  362.                     break;
  363.                 default:
  364.                     GetItem(GetMHandle(menu_id),
  365.                                     item,item_name);
  366.                     OpenDeskAcc(item_name);
  367.                     HiliteMenu(0);
  368.                     MaintainMenus();
  369.                     break;
  370.             }
  371.             break;
  372.         case file_menu:
  373.             switch (item)
  374.             {    case new_window:
  375.                     do_close(myWindow);
  376.                     myNewWindow();
  377.                     HiliteMenu(0);
  378.                     MaintainMenus();
  379.                     break;
  380.                 case graphic_window:
  381.                 case text_edit_window:
  382.                     CheckItem(GetMHandle(file_menu),
  383.                                     window_type,FALSE);
  384.                     window_type=item;
  385.                     CheckItem(GetMHandle(file_menu),
  386.                                     window_type,TRUE);
  387.                     break;
  388.                 case vert_bar:
  389.                     newCheck=has_vBar=1-has_vBar;
  390.                     break;
  391.                 case horiz_bar:
  392.                     newCheck=has_hBar=1-has_hBar;
  393.                     break;
  394.                 case vert_ruler:
  395.                     newCheck=has_vRuler=1-has_vRuler;
  396.                     break;
  397.                 case horiz_ruler:
  398.                     newCheck=has_hRuler=1-has_hRuler;
  399.                     break;
  400.                 case vert_tool_bar:
  401.                     newCheck=has_vTools=1-has_vTools;
  402.                     break;
  403.                 case horiz_tool_bar:
  404.                     newCheck=has_hTools=1-has_hTools;
  405.                     break;
  406.                 case quit:
  407.                     do_close(myWindow);
  408.                     finish();
  409.                 default:
  410.                     break;
  411.             }
  412.             if(item>=vert_bar)
  413.                 CheckItem(GetMHandle(file_menu),
  414.                                     item,newCheck);
  415.             break;
  416.         case edit_menu:
  417.             if(!SystemEdit(item-1))
  418.             {    switch(item-1)
  419.                 {    case undoCmd:
  420.                         break;
  421.                     case cutCmd:
  422.                         TECut(myhTE);
  423.                         break;
  424.                     case copyCmd:
  425.                         TECopy(myhTE);
  426.                         break;
  427.                     case pasteCmd:
  428.                         if(((long)(**myhTE).teLength+
  429.                             (long)TEGetScrapLen())<32760)
  430.                             TEPaste(myhTE);
  431.                         else
  432.                             SysBeep(10);
  433.                         break;
  434.                     case clearCmd:
  435.                         TEDelete(myhTE);
  436.                         break;
  437.                     default:
  438.                         break;
  439.                 }
  440.                 /* reset scroll bar */
  441.                 if(myScrlp->vScrollHdl!=NIL)
  442.                     SetScroll(myScrlp,(**myhTE).nLines,
  443.                                             VertBar);
  444.                 
  445.                 /* if needed, move insertion point */
  446.                 if(((item-1)==cutCmd)||
  447.                         ((item-1)==clearCmd)||
  448.                         ((item-1)==pasteCmd))
  449.                     FixTEInsertPt();
  450.             }
  451.         default:
  452.             break;
  453.     }
  454.     HiliteMenu(0);
  455. }
  456.  
  457. /* Handle Update events */
  458.  
  459. do_update(event)
  460.     EventRecord *event;
  461. {
  462.     WindowPtr up_wind=(WindowPtr)event->message;
  463.     
  464.     UpdateWindow(up_wind,FALSE);
  465. }
  466.  
  467. /* Update the window */
  468.  
  469. UpdateWindow(up_wind,scrollType)
  470.     WindowPtr up_wind;
  471.     int scrollType;
  472. {
  473.     GrafPtr save_graf;
  474.     
  475.     if(up_wind==myWindow)
  476.     {    GetPort(&save_graf);
  477.         SetPort(up_wind);
  478.         BeginUpdate(up_wind);
  479.         ClipRect(&up_wind->portRect);
  480.         EraseRect(&up_wind->portRect);
  481.         if(!scrollType)
  482.         {    DrawControls(up_wind);
  483.             ScrollDrawGrowIcon(myScrlp,up_wind);
  484.         }
  485.         draw_content(up_wind,scrollType);
  486.         EndUpdate(up_wind);
  487.         SetPort(save_graf);
  488.     }
  489. }
  490.  
  491. /*    Activate the window */
  492.  
  493. do_activate(act_wind,isactivate)
  494.     WindowPtr act_wind;
  495.     int isactivate;
  496. {
  497.     Rect r;
  498.     
  499.     SetPort(act_wind);
  500.     if(act_wind==myWindow)
  501.     {    ScrollDrawGrowIcon(myScrlp,act_wind);
  502.         if(isactivate)
  503.         {    ScrollActivate(myScrlp);
  504.             if(myhTE!=NIL)
  505.             {    TEActivate(myhTE);
  506.                 TEFromScrap();
  507.             }
  508.         }
  509.         else
  510.         {    ScrollDeactivate(myScrlp);
  511.             if(myhTE!=NIL)
  512.             {    TEDeactivate(myhTE);
  513.                 ZeroScrap();
  514.                 TEToScrap();
  515.             }
  516.         }
  517.     }
  518. }
  519.  
  520. /* handle window growing */
  521.  
  522. grow_window(windowp,mouse_point)
  523.     WindowPtr windowp;
  524.     Point mouse_point;
  525. {
  526.     long new_bounds;
  527.     
  528.     InvalBars(windowp);        /*invalidate scroll bars*/
  529.     if((new_bounds=GrowWindow(windowp,mouse_point,
  530.                     &dragrect))==0)
  531.         return;
  532.     SizeWindow(windowp,LoWord(new_bounds),
  533.                     HiWord(new_bounds),(Boolean)TRUE);
  534.     InvalBars(windowp);        /*invalidate new scroll bars*/
  535.     GrowScroll(windowp);    /*update scroll bar window*/
  536. }
  537.  
  538. /* Open new scrolling example window */
  539.  
  540. myNewWindow()
  541. {
  542.     Rect r,wrect;
  543.     int hLineSize=0,vLineSize=0,vTotalLines=0;
  544.     int vToolSize=0,vRulerSize=0,hToolSize=0,hRulerSize=0;
  545.     int vScrollTop=0,hScrollLeft=0,hTotalLines=0;
  546.     Boolean includeText=FALSE;
  547.     FontInfo theFont;
  548.     Handle texthdl;
  549.     
  550.     r=screenBits.bounds;
  551.     SetRect(&wrect,20,60,r.right-20,r.bottom-20);
  552.     myWindow=NewWindow(NIL,&wrect,"\pScrolling Example",
  553.                 1,documentProc,-1L,1,0L);
  554.  
  555.     polySize=0;
  556.     SetPort(myWindow);
  557.     TextFont(geneva);
  558.     TextSize(12);
  559.     /*Note: add 1 to ruler and tool widths for line*/
  560.     if(has_vRuler) vRulerSize=RULERWIDTH+1;
  561.     if(has_hRuler) hRulerSize=RULERWIDTH+1;
  562.     if(has_vTools)
  563.     {    vToolSize=TOOLWIDTH+1;
  564.         hScrollLeft=TOOLWIDTH+1;
  565.     }
  566.     if(has_hTools)
  567.     {    hToolSize=TOOLWIDTH+1;
  568.         vScrollTop=TOOLWIDTH+1;
  569.     }
  570.     if(has_hBar) hLineSize=18;
  571.     if(window_type==graphic_window)    
  572.     {    vTotalLines=hTotalLines=40;
  573.         if(has_vBar) vLineSize=18;
  574.     }
  575.     else
  576.     {    if(has_vBar)
  577.         {    GetFontInfo(&theFont);
  578.             vLineSize=theFont.ascent+theFont.descent+
  579.                                         theFont.leading;
  580.         }
  581.         vTotalLines=0;
  582.         if(has_hBar)
  583.             hTotalLines=(wrect.right-wrect.left-vToolSize-
  584.                     vRulerSize-SBarWidth)/hLineSize;
  585.         includeText=TRUE;
  586.     }
  587.  
  588.     /* Seto up scoll bars */
  589.     myScrlp=SetScrollWindow(myWindow,&scrollRecord,
  590.             includeText,vLineSize,vTotalLines,vToolSize,
  591.             vRulerSize,vScrollTop,hLineSize,hTotalLines,
  592.             hToolSize,hRulerSize,hScrollLeft,NIL);
  593.  
  594.      /*    If text window, add some sample text */
  595.     myhTE=myScrlp->hTE;
  596.     if(myhTE!=NIL)
  597.     {    texthdl=GetResource('GNRL',sample_text);
  598.         HLock(texthdl);
  599.         TESetText(*texthdl,SizeResource(texthdl),myhTE);
  600.         HUnlock(texthdl);
  601.         ReleaseResource(texthdl);
  602.         if(myScrlp->vScrollHdl!=NIL)
  603.             SetScroll(myScrlp,(**myhTE).nLines,VertBar);
  604.     }
  605.  
  606.     /* Set current window tool and ruler flags    */    
  607.     vTools=has_vTools;
  608.     hTools=has_hTools;
  609.     vRuler=has_vRuler;
  610.     hRuler=has_hRuler;    
  611. }
  612.  
  613. /* Draw the window contents */
  614.  
  615. draw_content(windowp,scrollType)
  616.     WindowPtr windowp;
  617.     int scrollType;
  618. {
  619.     register int i;
  620.     int lineSize=20,lm,tm,tick,nexttick;
  621.     int vtoolsize=0,htoolsize=0,xtick,ytick,vtotal,htotal;
  622.     static char vertTools[11]={10,'V','E','R','T',' ','T',
  623.                                 'O','O','L','S'};
  624.     static char horizTools[12]={11,'H','O','R','I','Z',
  625.                                 ' ','T','O','O','L','S'};
  626.     static int length[8]={0,5,8,5,11,5,8,5};
  627.     char nstr[20];
  628.     Rect drawRect,tempRect;
  629.     RgnHandle drawRgn;
  630.  
  631.     GetMargins(myScrlp,&lm,inPixels,&tm,inPixels);
  632.     ClipRect(NonScrollRect(myScrlp,windowp,&drawRect));
  633.     if(vTools) vtoolsize=TOOLWIDTH;
  634.     if(hTools) htoolsize=TOOLWIDTH;
  635.     
  636.     if(vTools&&(!scrollType))        /*vert tool bar*/
  637.     {    MoveTo(vtoolsize,drawRect.top);
  638.         LineTo(vtoolsize,drawRect.bottom);
  639.         TextFace(outline+bold+shadow);
  640.         for(i=1;i<=vertTools[0];i++)
  641.         {    MoveTo(0,htoolsize+20*i);
  642.             LineTo(vtoolsize,htoolsize+20*i);
  643.             MoveTo(6,htoolsize+20*i-5);
  644.             DrawChar(vertTools[i]);
  645.         }
  646.         TextFace(0);
  647.     }
  648.     
  649.     if(hTools&&(!scrollType))        /*horiz tool bar*/
  650.     {    MoveTo(drawRect.left,htoolsize);
  651.         LineTo(drawRect.right,htoolsize);
  652.         TextFace(outline+bold+shadow);
  653.         for(i=1;i<=horizTools[0];i++)
  654.         {    MoveTo(vtoolsize+25*i,0);
  655.             LineTo(vtoolsize+25*i,htoolsize);
  656.             MoveTo(vtoolsize+25*i-17,15);
  657.             DrawChar(horizTools[i]);
  658.         }
  659.         TextFace(0);
  660.     }
  661.                     
  662.     if(vTools&&hTools&&(!scrollType))
  663.         markX(0,0,htoolsize,vtoolsize);
  664.     
  665.     if(vRuler&&hRuler&&(!scrollType))
  666.         markX(vtoolsize,htoolsize,RULERWIDTH,RULERWIDTH);
  667.     
  668.     TextSize(9);
  669.     if(vRuler&&(scrollType!=HorizBar))
  670.     {    vtotal=vtoolsize+RULERWIDTH;
  671.         MoveTo(vtotal,drawRect.top+htoolsize);
  672.         LineTo(vtotal,drawRect.bottom);
  673.         drawRect.top=htoolsize+RULERWIDTH*hRuler;
  674.         ClipRect(&drawRect);
  675.         tick=tm/72;
  676.         nexttick=drawRect.top+72*tick-tm-72;
  677.         while((nexttick+=72)<=drawRect.bottom)
  678.         {    MoveTo(vtoolsize,nexttick);
  679.             LineTo(vtotal,nexttick);
  680.             if(tick)
  681.             {    NumToString((long)tick,nstr);
  682.                 MoveTo(vtotal-StringWidth(nstr),
  683.                                         nexttick+8);
  684.                 DrawString(nstr);
  685.             }
  686.             for(i=1;i<=7;i++)
  687.             {    MoveTo(vtotal,ytick=nexttick+9*i);
  688.                 LineTo(vtotal-length[i],ytick);
  689.             }
  690.             tick++;
  691.         }
  692.     }
  693.     
  694.     if(hRuler&&(scrollType!=VertBar))
  695.     {    htotal=htoolsize+RULERWIDTH;
  696.         drawRect.top=0;
  697.         ClipRect(&drawRect);
  698.         MoveTo(drawRect.left+vtoolsize,htotal);
  699.         LineTo(drawRect.right,htotal);
  700.         drawRect.left=vtoolsize+RULERWIDTH*vRuler;
  701.         ClipRect(&drawRect);
  702.         tick=lm/72;
  703.         nexttick=drawRect.left+72*tick-lm-72;
  704.         while((nexttick+=72)<=drawRect.right+8)
  705.         {    MoveTo(nexttick,htoolsize);
  706.             LineTo(nexttick,htotal);
  707.             if(tick)
  708.             {    NumToString((long)tick,nstr);
  709.                 MoveTo(nexttick-1-StringWidth(nstr),
  710.                             htoolsize+10);
  711.                 DrawString(nstr);
  712.             }
  713.             for(i=1;i<=7;i++)
  714.             {    MoveTo(xtick=nexttick+9*i,htotal);
  715.                 LineTo(xtick,htotal-length[i]);
  716.             }
  717.             tick++;
  718.         }
  719.     }
  720.     TextSize(12);
  721.     
  722.     if(myhTE==NIL)            /*Graphic Window Update*/
  723.     {    drawRgn=ScrollSectRgn(myScrlp,windowp);
  724.         SetClip(drawRgn);
  725.         MoveTo(polygon[0].h-lm,polygon[0].v-tm);
  726.         for(i=1;i<=polySize;i++)
  727.             LineTo(polygon[i].h-lm,polygon[i].v-tm);
  728.         ClipRect(&windowp->portRect);
  729.         DisposeRgn(drawRgn);
  730.     }
  731.     else                    /*Text Window Update*/
  732.     {    ClipRect(&windowp->portRect);
  733.         tempRect=(**myhTE).viewRect;
  734.         TEUpdate(&tempRect,myhTE);
  735.     }
  736. }
  737.  
  738. /*    Draw X in window    */
  739.  
  740. markX(beginx,beginy,xwidth,ywidth)
  741. int beginx,beginy,xwidth,ywidth;
  742. {    MoveTo(beginx,beginy);
  743.     LineTo(beginx+xwidth,beginy+ywidth);
  744.     MoveTo(beginx,beginy+ywidth);
  745.     LineTo(beginx+xwidth,beginy);
  746. }
  747.  
  748. /* Present about box and wait for mouse click */
  749.  
  750. do_about()
  751. {
  752.     DialogPtr aboutBox;
  753.     EventRecord event;
  754.     
  755.     aboutBox=GetNewDialog(about_dlog,NIL,-1L);
  756.     DrawDialog(aboutBox);
  757.     
  758.     /* wait for key or mouse click - 
  759.                     from MacTutor, V4,#3,pg10 */
  760.     while(!EventAvail(keyDownMask|autoKeyMask|mDownMask,
  761.                             &event))
  762.         SystemTask();
  763.     
  764.     if(event.what==mouseDown)    /* remove mouse down */
  765.     {    GlobalToLocal(&event.where);
  766.         if(PtInRect(event.where,&aboutBox->portRect))
  767.             GetNextEvent(mDownMask,&event);
  768.     }
  769.     
  770.     DisposDialog(aboutBox);
  771. }
  772.  
  773. /* Exit to shell after saving TE scrap */
  774.  
  775. finish()
  776. {
  777.     ZeroScrap();
  778.     TEToScrap();
  779.     LoadScrap();
  780.     ExitToShell();
  781. }
  782.